package com.base.thread.demo_24;

import java.util.ArrayList;
import java.util.List;

/**
 * 第一个线程调用lock()，isLocked=true
 * 之后的线程调用lock()拿锁，new queueObject()存入队列并wait()
 * 第一个线程执行完毕调用unlock()，isLocked=false，取出队列头部的queueObject对象notify()，
 * 保证了先wait的线程按顺序先notify(即公平性)
 * 
 * 1.synchronized的同步块走完就会释放锁，没有嵌套，不存在死锁和嵌套锁死
 */
public class FairLock {
    private boolean isLocked = false;
    private Thread lockingThread = null;
    private List<QueueObject> waitingThreads = new ArrayList<QueueObject>();

    public void lock() throws InterruptedException {
        QueueObject queueObject = new QueueObject();
        boolean isLockedForThisThread = true;
        synchronized (this) {
            waitingThreads.add(queueObject);
        }

        while (isLockedForThisThread) {
            synchronized (this) {
            	//雷同下面if语句
            	isLockedForThisThread = isLocked || waitingThreads.get(0) != queueObject;
//            	if (waitingThreads.get(0) == queueObject) {
//            		isLockedForThisThread = isLocked;
//				}
                if (!isLockedForThisThread) {
                    isLocked = true;
                    waitingThreads.remove(queueObject);
                    lockingThread = Thread.currentThread();
                    return;
                }
            }
            try {
                queueObject.doWait();
            } catch (InterruptedException e) {
                synchronized (this) {
                    waitingThreads.remove(queueObject);
                }
                throw e;
            }
        }
    }

    public synchronized void unlock() {
        if (this.lockingThread != Thread.currentThread()) {
            throw new IllegalMonitorStateException("Calling thread has not locked this lock");
        }
        isLocked = false;
        lockingThread = null;
        if (waitingThreads.size() > 0) {
            waitingThreads.get(0).doNotify();
        }
    }
}